package wangjg.commons.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;

public class BasicHTemplateDAO<T, ID extends Serializable> extends AbstractBasicAO<T, ID> {
	protected Class<T> persistentClass;

	private HibernateTemplate hbTemplate;

	public BasicHTemplateDAO() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public HibernateTemplate getHbTemplate() {
		return hbTemplate;
	}

	public void setHbTemplate(HibernateTemplate dbTemplate) {
		this.hbTemplate = dbTemplate;
	}
	
	int _________________;

	/**
	 * 保存新增对象.
	 */
	public ID save(final T entity) {
		ID id = (ID) getHbTemplate().save(entity);
		return id;
	}

	/**
	 * 保存新增或修改的对象.
	 */
	public void update(final T entity) {
		getHbTemplate().update(entity);
	}

	/**
	 * 保存新增或修改的对象
	 */
	public void saveOrUpdate(final T entity) {
		getHbTemplate().saveOrUpdate(entity);
	}

	/**
	 * 删除对象.
	 * 
	 * @param entity 对象必须是session中的对象或含id属性的transient对象.
	 */
	public void delete(final T entity) {
		getHbTemplate().delete(entity);
	}
	public void delete(ID id) {
		this.delete(this.get(id));
	}
	public T findByProperty(String propertyName, Object value) {
		String hql = "from "+this.persistentClass.getSimpleName()+" where "+propertyName+"=?";
		return (T) this.queryUnique(hql, value);
	}

	public <N extends Number> N findCountByProperty(String propertyName, Object propertyValue){
		String hql = "select count(*) from "+this.persistentClass.getSimpleName()+" where "+propertyName+"=?";
		Object o = this.queryUnique(hql, propertyValue);
		N count = (N)o;
		return count;
	}

	public List findPropertyList(String returnProperty){
		return this.findPropertyList(returnProperty, null, null, null, null, null, null);
	}

	public List findPropertyList(String returnProperty, String fieldname, Object value){
		return this.findPropertyList(returnProperty, fieldname, value, null, null, null, null);
	}

	public List findPropertyList(String returnProperty, String filterProperty, Object filterValue ,String orderby, Boolean asc, Integer firstResult, Integer maxResults){
		this.checkProperty(returnProperty);
		this.checkProperty(filterProperty);
		this.checkProperty(orderby);
		String hql = "select distinct "+returnProperty+" from "+this.persistentClass.getSimpleName();
		if(filterProperty!=null && filterValue!=null){
			hql += " where "+filterProperty+"=?";
		}
		if(orderby!=null){
			String order = (Boolean.TRUE.equals(asc)?" order by "+orderby:" order by "+orderby+" desc");
			hql += order;
		}
		List result = null;
		if(filterProperty!=null && filterValue!=null){
			if(firstResult!=null && maxResults!=null){
				result = this.query(firstResult, maxResults, hql, filterValue);
			}else{
				result = this.query(hql, filterValue);
			}
		}else{
			if(firstResult!=null && maxResults!=null){
				result = this.query(firstResult, maxResults, hql);
			}else{
				result = this.query(hql);
			}
		}
		return result;
	}

	/**
	 * 按HQL查询对象列表
	 * @param hql
	 * @param values
	 * @return 对象集合
	 */
	protected List query(final String hql, final Object... values) {
		return getHbTemplate().find(hql, values);
	}
	
	protected List query(final int firstResult, final int maxResults, final String hql, final Object... values) {
		HibernateCallback<Object> action=new HibernateCallback<Object>(){
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query=createQuery(session, hql, values);
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
				Object result = query.list();
				return result;
			}
			
		};
		return getHbTemplate().executeFind(action);
	}
	
	/**
	 * 按HQL查询唯一对象.
	 * 
	 * @param values
	 * 数量可变的参数,按顺序绑定. 
	 */
	protected Object queryUnique(final String hql, final Object... values) {
		HibernateCallback<Object> action=new HibernateCallback<Object>(){

			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query=createQuery(session, hql, values);
				Object result = query.uniqueResult();
				return result;
			}
			
		};
		return getHbTemplate().execute(action);
	}

	protected int executeUpdate(final String hql, final Object... values) {
		HibernateCallback<Object> action=new HibernateCallback<Object>(){
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query=createQuery(session, hql, values);
				int result = query.executeUpdate();
				return result;
			}
			
		};
		Object obj = getHbTemplate().execute(action);
		return (Integer) obj;
	}

	protected T get(ID id) {
		return getHbTemplate().get(persistentClass, id);
	}

	protected T load(ID id) {
		return getHbTemplate().load(persistentClass, id);
	}

	/**
	 * 合并对象.
	 */
	protected void merge(final T entity) {
		getHbTemplate().merge(entity);
	}

	/////////////////
	
	
	protected Query createQuery(Session session, final String queryString, final Object...values) {
		Assert.hasText(queryString, "queryString不能为空");
		Query query = session.createQuery(queryString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query;
	}

	protected List findByNamedParam(String queryString, String paramName, Object value){
		return this.getHbTemplate().findByNamedParam(queryString, paramName, value);
	}

}
